﻿using GoodroommateComputingPlatform.Algorithms.Kmeans;
using GoodroommateComputingPlatform.Models.Goodroommate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace GoodroommateComputingPlatform.Tasks.Goodroommate
{
    public class GroupUserInfoTasks
    {
        private ITaskManager _tm;
        private GoodroomDbContext _context;

        public const string TaskOfGroupUserInfo = "gr-GroupUserInfo";

        public const string KeyOfGroupUserInfoStartDateTime = "computing.gr-GroupUserInfo.starttime.local";
        public const string KeyOfGroupUserInfoCompleteDateTime = "computing.gr-GroupUserInfo.completetime.local";

        public GroupUserInfoTasks(ITaskManager tm, GoodroomDbContext context)
        {
            _tm = tm;
            _context = context;
            tm.RegisterTask(TaskOfGroupUserInfo, GroupUserInfo, this);
        }

        private static object GroupUserInfo(object globls, object state)
        {
            var self = (GroupUserInfoTasks)globls;
            
            WriteDateTime(self._context, KeyOfGroupUserInfoStartDateTime);

            try
            {
                DoTempGroupUserInfo(self._context);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                WriteDateTime(self._context, KeyOfGroupUserInfoCompleteDateTime);
            }
            return null;
        }

        private static int WriteDateTime(GoodroomDbContext context, string key)
        {
            var tk = context.keydata.Where(k => k.Key == key);
            if (tk.Count() > 0)
                tk.First().Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            else
                context.keydata.Add(new KeyData()
                {
                    Key = key,
                    Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                });
            return context.SaveChanges();
        }

        private static int ParseTime(string time)
        {
            short h = Convert.ToInt16(time.Substring(0, 2));
            short m = Convert.ToInt16(time.Substring(3, 2));
            short s = Convert.ToInt16(time.Substring(6, 2));
            return 3600 * h + 60 * m + s;
        }


        private static void DoTempGroupUserInfo(GoodroomDbContext context)
        {
            // 获取数据
            var dataset = from item in context.temp     
                          select new UserInfoModel()
                          {
                              UserID = item.ID,
                              Username = item.Username,
                              UniversityID = item.University,
                              Name=item.Name,
                              Gender = item.Gender,
                              SleepTime = item.SleepTime,
                              WakeupTime = item.WakeupTime,
                              Belief = item.Belief,
                              Nation = item.Nation
                          };
            var list = dataset.ToList();

            // 定义Vector
            KmeansVectorAction<UserInfoModel> vectorAction = (obj, vector) =>
            {
                // 学校
                vector.Add(obj.UniversityID);
                // 性别
                vector.Add(obj.Gender == "女" ? 0 : 1000);
                // 起床时间
                int time;
                try
                {
                    time = ParseTime(obj.WakeupTime);
                    vector.Add(time);
                }
                catch (FormatException)
                {
                    vector.Add(0);
                }
                // 睡觉时间
                try
                {
                    time = ParseTime(obj.SleepTime);
                    if (time < 12 * 3600) // 早晨睡觉的人
                        time += 24 * 3600;
                    vector.Add(time);
                }
                catch (FormatException)
                {
                    vector.Add(0);
                }
            };

            // 开始执行聚类算法
            var kmeans = new KmeansCore<UserInfoModel>();
            kmeans.VectorAction = vectorAction;
            kmeans.GroupCount = 400;
            var result = kmeans.DoKmeans(list);

            // 存储聚类结果
            foreach (var item in context.userinfo_grouped.ToArray())
            {
                context.userinfo_grouped.Remove(item);
                context.SaveChanges();
            }
            context.SaveChanges();
            int groupId = 0;
            foreach (var group in result)
            {
                groupId++;
                foreach (var item in group)
                {
                    context.userinfo_grouped.Add(new UserInfoGrouped() { UserID = item.UserID, GroupID = groupId });
                    //context.SaveChanges();
                }
            }
            context.SaveChanges();
        }



        private static void DoGroupUserInfo(GoodroomDbContext context)
        {
            // 获取数据
            var dataset = from user in context.users
                          join userdetail in context.userdetails
                          on user.ID equals userdetail.UserID
                          join userinfo in context.userinfo
                          on user.ID equals userinfo.UserID
                          join university in context.universities
                          on userdetail.University equals university.ID
                          select new UserInfoModel()
                          {
                              UserID = user.ID,
                              Username = user.Username,
                              UniversityID = userdetail.University,
                              Gender = userdetail.Gender,
                              SleepTime = userinfo.SleepTime,
                              WakeupTime = userinfo.WakeupTime,
                              Belief = userdetail.Belief,
                              Nation = userdetail.Nation
                          };
            var list = dataset.ToList();

            // 定义Vector
            KmeansVectorAction<UserInfoModel> vectorAction = (obj, vector) =>
            {
                // 学校
                vector.Add(obj.UniversityID);
                // 性别
                vector.Add(obj.Gender == "女" ? 0 : 1);
                // 起床时间
                int time;
                try
                {
                    time = ParseTime(obj.WakeupTime);
                    vector.Add(time);
                }
                catch (FormatException)
                {
                    vector.Add(0);
                }
                // 睡觉时间
                try
                {
                    time = ParseTime(obj.SleepTime);
                    if (time < 12 * 3600) // 早晨睡觉的人
                        time += 24 * 3600;
                    vector.Add(time);
                }
                catch (FormatException)
                {
                    vector.Add(0);
                }
            };

            // 开始执行聚类算法
            var kmeans = new KmeansCore<UserInfoModel>();
            kmeans.VectorAction = vectorAction;
            kmeans.GroupCount = 5;
            var result = kmeans.DoKmeans(list);

            // 存储聚类结果
            foreach (var item in context.userinfo_grouped.ToArray())
            {
                context.userinfo_grouped.Remove(item);
                context.SaveChanges();
            }
            context.SaveChanges();
            int groupId = 0;
            foreach (var group in result)
            {
                groupId++;
                foreach (var item in group)
                {
                    context.userinfo_grouped.Add(new UserInfoGrouped() { UserID = item.UserID, GroupID = groupId });
                    context.SaveChanges();
                }
            }
            context.SaveChanges();
        }
    }
}
